package com.my.blog.website.service.impl;

import com.github.pagehelper.PageHelper;
import com.my.blog.website.constant.WebConst;
import com.my.blog.website.dao.MetaVoMapper;
import com.my.blog.website.dto.MetaDto;
import com.my.blog.website.dto.Types;
import com.my.blog.website.exception.TipException;
import com.my.blog.website.modal.Vo.ContentVo;
import com.my.blog.website.modal.Vo.MetaVo;
import com.my.blog.website.modal.Vo.RelationshipVoKey;
import com.my.blog.website.service.IContentService;
import com.my.blog.website.service.IMetaService;
import com.my.blog.website.service.IRelationshipService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by BlueT on 2017/3/17.
 */
@Service
public class MetaServiceImpl implements IMetaService {
    private static final Logger LOGGER = LoggerFactory.getLogger(MetaServiceImpl.class);

    @Resource
    private MetaVoMapper metaDao;

    @Resource
    private IRelationshipService relationshipService;

    @Resource
    private IContentService contentService;

    @Override
    public MetaDto getMeta(String type, String name) {
        if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(name)) {
            return metaDao.selectDtoByNameAndType(name, type);
        }
        return null;
    }

    @Override
    public Integer countMeta(Integer mid) {
        return metaDao.countWithSql(mid);
    }

    @Override
    public List<MetaVo> getMetas(String types) {
        return getMetas(null, types);
    }

    @Override
    public List<MetaVo> getMetas(Integer uid, String types) {
        Example example = new Example(MetaVo.class);
        Example.Criteria criteria = example.createCriteria();
        if (null!=uid) {
            criteria.andEqualTo("ownerId",uid);
        }
        if (StringUtils.isNotBlank(types)) {
            criteria.andEqualTo("type",types);
        }

        example.setOrderByClause("sort desc, mid desc");
        return metaDao.selectByExample(example);
    }

    @Override
    public List<MetaDto> getMetaList(String type, String orderby, int limit) {
        return getMetaList(null, type, orderby, limit);
    }

    @Override
    public List<MetaDto> getMetaList(Integer uid,String type, String orderby, int limit) {
        if (StringUtils.isNotBlank(type)) {
            if (limit < 1 || limit > WebConst.MAX_POSTS) {
                limit = 10;
            }

            Example example = new Example(MetaVo.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("type",type);
            if (null!=uid){
                criteria.andEqualTo("ownerId",uid);
            }
            if (StringUtils.isBlank(orderby)) {
                orderby = "citation_times desc, mid desc";
                example.setOrderByClause(orderby);
            }
            PageHelper.startPage(1,limit);
            List<MetaVo> list = metaDao.selectByExample(example);
            if(null!=list && list.size()>0){
                List<MetaDto> dtoList =  new ArrayList<>();
                for (MetaVo metaVo : list){
                    MetaDto metaDto = new MetaDto();
                    BeanUtils.copyProperties(metaVo,metaDto);
                    metaDto.setCount(metaVo.getCitationTimes());

                    dtoList.add(metaDto);
                }

                return dtoList;
            }
        }
        return null;
    }

    @Override
    @Transactional
    public void delete(int mid) {
        MetaVo metas = metaDao.selectByPrimaryKey(mid);
        if (null != metas) {
            String type = metas.getType();
            String name = metas.getName();

            metaDao.deleteByPrimaryKey(mid);

            List<RelationshipVoKey> rlist = relationshipService.getRelationshipById(null, mid);
            if (null != rlist) {
                for (RelationshipVoKey r : rlist) {
                    ContentVo contents = contentService.getContents(String.valueOf(r.getCid()));
                    if (null != contents) {
                        ContentVo temp = new ContentVo();
                        temp.setCid(r.getCid());
                        if (type.equals(Types.CATEGORY.getType())) {
                            temp.setCategories(reMeta(name, contents.getCategories()));
                        }
                        if (type.equals(Types.TAG.getType())) {
                            temp.setTags(reMeta(name, contents.getTags()));
                        }
                        contentService.updateContentByCid(temp);
                    }
                }
            }
            relationshipService.deleteById(null, mid);
        }
    }

    @Override
    @Transactional
    public void saveMeta(Integer uid, String type, String name, Integer mid) {
        if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(name)) {
            /*MetaVoExample metaVoExample = new MetaVoExample();
            metaVoExample.createCriteria().andTypeEqualTo(type).andNameEqualTo(name);
            List<MetaVo> metaVos = metaDao.selectByExample(metaVoExample);*/
            Example example = new Example(MetaVo.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("type",type).andEqualTo("name",name);
            if (null != uid){
                criteria.andEqualTo("ownerId",uid);
            }
            List<MetaVo> metaVos = metaDao.selectByExample(example);
            MetaVo metas;
            if (metaVos.size() != 0) {
                throw new TipException("已经存在该项");
            } else {
                metas = new MetaVo();
                metas.setName(name);
                if (null != mid) {
                    //更新
                    MetaVo original = metaDao.selectByPrimaryKey(mid);
                    metas.setMid(mid);
                    metaDao.updateByPrimaryKeySelective(metas);
//                    更新原有文章的categories
                    contentService.updateCategory(original.getName(), name);
                } else {
                    //新增
                    metas.setType(type);
                    metas.setOwnerId(uid);
                    metaDao.insertSelective(metas);
                }
            }
        }
    }

    @Override
    @Transactional
    public void saveMetas(Integer uid, Integer cid, String names, String type,String newStatus,String oldStatus) {
        if (null == cid) {
            throw new TipException("项目关联id不能为空");
        }
        if (StringUtils.isNotBlank(names) && StringUtils.isNotBlank(type)) {
            String[] nameArr = StringUtils.split(names, ",");
            for (String name : nameArr) {
                this.saveOrUpdate(uid, cid, name, type,newStatus,oldStatus);
            }
        }
    }

    /**
     * 保存或者更新
     *
     * @param cid
     * @param name
     * @param type
     * @param newStatus 旧状态
     * @param oldStatus 新状态
     */
    private void saveOrUpdate(Integer uid, Integer cid, String name, String type,String newStatus,String oldStatus) {
        /*MetaVoExample metaVoExample = new MetaVoExample();
        metaVoExample.createCriteria().andTypeEqualTo(type).andNameEqualTo(name);
        List<MetaVo> metaVos = metaDao.selectByExample(metaVoExample);*/
        // 1. 先查询
        Example example = new Example(MetaVo.class);
        example.createCriteria().andEqualTo("ownerId",uid).andEqualTo("type",type).andEqualTo("name",name);
        List<MetaVo> metaVos = metaDao.selectByExample(example);

        int mid;
        MetaVo metas;
        if (metaVos.size() == 1) {
            metas = metaVos.get(0);
            mid = metas.getMid();

            boolean updatable = Boolean.TRUE;
            //发布--> 其他状态  减1
            if (Types.PUBLISH.getType().equals(oldStatus)
                    && !Types.PUBLISH.getType().equals(newStatus)){
                if(metas.getCitationTimes()>0){
                    metas.setCitationTimes(metas.getCitationTimes()-1);
                }else{
                    metas.setCitationTimes(0);
                }
            }else if (!Types.PUBLISH.getType().equals(oldStatus) && Types.PUBLISH.getType().equals(newStatus)){
                //其他状态 --> 发布状态 加1
                metas.setCitationTimes(metas.getCitationTimes()+1);
            }else {
                updatable = Boolean.FALSE;
            }

            if (updatable){
                metaDao.updateByPrimaryKeySelective(metas);
            }
        } else if (metaVos.size() > 1) {
            throw new TipException("查询到多条数据");
        } else {
            // 新增
            metas = new MetaVo();
            metas.setSlug(name);
            metas.setName(name);
            metas.setType(type);
            metas.setOwnerId(uid);
            if(Types.PUBLISH.getType().equals(newStatus)){
                // 设置引用次数=1
                metas.setCitationTimes(1);
            }else {
                metas.setCitationTimes(0);
            }

            metaDao.insertSelective(metas);
            mid = metas.getMid();
        }
        if (mid != 0) {
            Long count = relationshipService.countById(cid, mid);
            if (count == 0) {
                RelationshipVoKey relationships = new RelationshipVoKey();
                relationships.setCid(cid);
                relationships.setMid(mid);
                //新状态不是发布都设置为删除
                relationships.setDelFlag(!Types.PUBLISH.getType().equals(newStatus));
                relationshipService.insertVo(relationships);
            }
        }
    }


    private String reMeta(String name, String metas) {
        String[] ms = StringUtils.split(metas, ",");
        StringBuilder sbuf = new StringBuilder();
        for (String m : ms) {
            if (!name.equals(m)) {
                sbuf.append(",").append(m);
            }
        }
        if (sbuf.length() > 0) {
            return sbuf.substring(1);
        }
        return "";
    }

    @Override
    @Transactional
    public void saveMeta(MetaVo metas) {
        if (null != metas) {
            metaDao.insertSelective(metas);
        }
    }

    @Override
    @Transactional
    public void update(MetaVo metas) {
        if (null != metas && null != metas.getMid()) {
            metaDao.updateByPrimaryKeySelective(metas);
        }
    }
}
